﻿using System.Web.Security;
using System.Text;
using System.IO;
using System.Web;
using System.Configuration;
using System.Security.Cryptography;
using System;
namespace WxSDK.Common
{
    public class RSAEncrypt
    {
        string path = "Key";


        public RSAEncrypt()
        {
            GetKey(path);
        }

        public RSAEncrypt(string _path)
        {
            this.path = _path;
            GetKey(path);
        }

        #region Static
        
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="Source"></param>
        /// <returns></returns>
        public static string Md5Encrypt(string Source)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(Source, "MD5");
        }
        
        public static string BytesToHexString(byte[] input)
        {
            StringBuilder hexString = new StringBuilder(64);

            for (int i = 0; i < input.Length; i++)
            {
                hexString.Append(string.Format("{0:X2}", input[i]));
            }
            return hexString.ToString();
        }

        public static byte[] HexStringToBytes(string hex)
        {
            if (hex.Length == 0)
            {
                return new byte[] { 0 };
            }

            if (hex.Length % 2 == 1)
            {
                hex = "0" + hex;
            }

            byte[] result = new byte[hex.Length / 2];

            for (int i = 0; i < hex.Length / 2; i++)
            {
                result[i] = byte.Parse(hex.Substring(2 * i, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
            }

            return result;
        }

        #endregion

        #region 属性

        private string _PublicKeyModulus;

        public string PublicKeyModulus
        {
            get { return _PublicKeyModulus; }
            set { _PublicKeyModulus = value; }
        }

        private string _PublicKeyExponent;

        public string PublicKeyExponent
        {
            get { return _PublicKeyExponent; }
            set { _PublicKeyExponent = value; }
        }

        private string _PrivateKey;

        public string PrivateKey
        {
            get { return _PrivateKey; }
            set { _PrivateKey = value; }
        }

        #endregion

        void GetKey(string path)
        {
            if (!Directory.Exists(HttpContext.Current.Server.MapPath("~/" + path)))
            {
                Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/" + path));
                SetKey(path);
            }
            else
            {
                _PublicKeyModulus = ReadAllText("~/" + path + "/PublicKeyModulus.config");
                _PublicKeyExponent = ReadAllText("~/" + path + "/PublicKeyExponent.config");
                _PrivateKey = ReadAllText("~/" + path + "/PrivateKey.config");
            }
        }

        void SetKey(string path)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            PrivateKey = rsa.ToXmlString(true);
            RSAParameters parameter = rsa.ExportParameters(true);
            PublicKeyExponent = BytesToHexString(parameter.Exponent);
            PublicKeyModulus = BytesToHexString(parameter.Modulus);
            File.WriteAllText(HttpContext.Current.Server.MapPath("~/" + path + "/PublicKeyExponent.config"), PublicKeyExponent);
            File.WriteAllText(HttpContext.Current.Server.MapPath("~/" + path + "/PublicKeyModulus.config"), PublicKeyModulus);
            File.WriteAllText(HttpContext.Current.Server.MapPath("~/" + path + "/PrivateKey.config"), PrivateKey);
        }

        string ReadAllText(string path)
        {
            var _path = HttpContext.Current.Server.MapPath(path);

            if (File.Exists(_path))            
                return File.ReadAllText(_path);
            
            else
                SetKey(path.Substring(0,path.LastIndexOf('/')).Replace("~/",""));

            return string.Empty;
        }

        public string Dencrypt(string password)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(PrivateKey);
            ASCIIEncoding enc = new ASCIIEncoding();
            byte[] result = rsa.Decrypt(HexStringToBytes(password), false);
            return enc.GetString(result);
        }

        public string Encrypt(string password)
        {
            RSAParameters parameters = new RSAParameters();

            parameters.Modulus = HexStringToBytes(PublicKeyModulus);

            parameters.Exponent = HexStringToBytes(PublicKeyExponent);

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

            rsa.ImportParameters(parameters);

            byte[] result = rsa.Encrypt(new UnicodeEncoding().GetBytes(password), false);

            return BytesToHexString(result).ToLower();
        }
    }
}